package de.yellowshoes.gtugrm.googleplus.gae;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberInputStream;
import java.io.LineNumberReader;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessProtectedResource;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAuthorizationRequestUrl;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;

public abstract class GooglePlusServlet extends HttpServlet implements Constants {

	protected String accessToken = null;
	protected String refreshToken = null;
	protected HttpSession session = null;
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -2086320985747013189L;

	@Override
	protected final void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		if( processRequest(req, resp) == false ){
			doSubGet(req, resp);
		}
	}

	@Override
	protected final void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		if( processRequest(req, resp) == false ){
			doSubPost(req, resp);
		}
	}

	private final boolean processRequest(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		boolean redirectInProcress = false;
		session = req.getSession(true);
		if( session != null ){
			accessToken = ( String )session.getAttribute( SESSION_PARM_ACCESS_TOKEN );
			refreshToken = ( String )session.getAttribute(SESSION_PARM_REFRESH_TOKEN);
			
			if( accessToken == null || refreshToken == null ){
				// error while auth request, maybe no authorization
				if( req.getParameter( "error" ) != null ){
					
				}
				// start new auth request
				else if( req.getParameter( "code" ) == null ){
					doAuthRequest( req, resp );
					redirectInProcress = true;
				}
				// redirect from auth request
				else{
					doAuthExtract( req, resp );
					redirectInProcress = true;
				}
			}
		}
		
		return redirectInProcress;
	}

	private void doAuthExtract(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		String code = req.getParameter( "code" );
		HttpTransport TRANSPORT = new NetHttpTransport();
		JsonFactory JSON_FACTORY = new JacksonFactory();
		GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, code, getRedirectUrl(req));
		authRequest.useBasicAuthorization = false;
		AccessTokenResponse authResponse = authRequest.execute();
		String accessToken = authResponse.accessToken;
		
		if( session != null )
		{
			session.setAttribute( SESSION_PARM_ACCESS_TOKEN, accessToken);
			session.setAttribute(SESSION_PARM_REFRESH_TOKEN, authResponse.refreshToken);
			this.accessToken = accessToken;
			this.refreshToken = authResponse.refreshToken;
		}
		
		resp.sendRedirect( getRedirectUrl(req));
	}

	private void doAuthRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		String redirectUrl = getRedirectUrl(req);
		String authorizeUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, redirectUrl, SCOPE_GOOGLE_PLUS ).build();
		resp.sendRedirect(authorizeUrl);
	}

	private String getRedirectUrl( HttpServletRequest req ){
		return "http://" + req.getServerName() + ":" + req.getLocalPort() + "/start";
	}
	
	protected abstract void doSubPost(HttpServletRequest req,
			HttpServletResponse resp) throws ServletException, IOException;

	protected abstract void doSubGet(HttpServletRequest req,
			HttpServletResponse resp) throws ServletException, IOException;
	
	protected String readTemplate( String templatePath ) throws IOException{
		StringBuffer buffer = new StringBuffer();
		
		LineNumberReader in = new LineNumberReader( new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream( templatePath )));
		String tempBuffer = null;
		
		do{
			tempBuffer = in.readLine();
			if( tempBuffer != null ){
				buffer.append( tempBuffer ).append( "\n" );
			}
		} while( tempBuffer != null );
		
		return buffer.toString();
	}
}
